home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Communications / pcomm / Source / curses.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-12  |  8.6 KB  |  493 lines

  1. /*
  2.  * Miscellaneous curses(3) routines.
  3.  */
  4.  
  5. #define STR_WIDTH    256
  6. #define NUM_WIDTH    16
  7.  
  8. #include <stdio.h>
  9. #include <curses.h>
  10. #include <signal.h>
  11. #include "config.h"
  12. #include "misc.h"
  13.  
  14. #ifdef BSD
  15. #include <setjmp.h>
  16. jmp_buf wk_buf;
  17. #endif /* BSD */
  18.  
  19. #ifndef OLDCURSES
  20. #include <term.h>
  21. #else /* OLDCURSES */
  22. #ifdef UNIXPC
  23. #include <sgtty.h>
  24. #endif /* UNIXPC */
  25. #endif /* OLDCURSES */
  26.  
  27. /*
  28.  * Get a string from a window.  Similar to wgetstr(), except we limit
  29.  * the length, return a NULL (not pointer to NULL) on <ESC> key, beep
  30.  * at any character in "disallow" string, and beep at any character not
  31.  * in "allow". (It doesn't make sense to use both "allow" and "disallow"
  32.  * at the same time).  Returns a pointer to a static area.
  33.  */
  34.  
  35. char *
  36. get_str(win, num, allow, disallow)
  37. WINDOW *win;
  38. int num;
  39. char *allow, *disallow;
  40. {
  41.     int count, x, y;
  42.     char ans, *strchr();
  43.     static char buf[STR_WIDTH];
  44.  
  45.     count = 0;
  46.     while ((ans = wgetch(win)) != '\r') {
  47.                     /* do our own backspace */
  48.         if (ans == BS || ans == DEL) {
  49.             if (!count) {
  50.                 beep();
  51.                 continue;
  52.             }
  53.             count--;
  54.             buf[count] = '\0';
  55.             getyx(win, y, x);
  56.             x--;
  57.             wmove(win, y, x);
  58.             waddch(win, (chtype) ' ');
  59.             wmove(win, y, x);
  60.             wrefresh(win);
  61.             continue;
  62.         }
  63.                     /* an <ESC> anywhere in the string */
  64.         if (ans == ESC)
  65.             return(NULL);
  66.  
  67.                     /* illegal character? */
  68.         if (*disallow != '\0' && strchr(disallow, ans)) {
  69.             beep();
  70.             continue;
  71.         }
  72.         if (*allow != '\0' && !strchr(allow, ans)) {
  73.             beep();
  74.             continue;
  75.         }
  76.                     /* exceeded the max? */
  77.         if (count >= num || count >= STR_WIDTH) {
  78.             beep();
  79.             continue;
  80.         }
  81.  
  82.         buf[count] = ans;
  83.         waddch(win, (chtype) ans);
  84.         wrefresh(win);
  85.         count++;
  86.     }
  87.     buf[count] = '\0';
  88.     return(buf);
  89. }
  90.  
  91. /*
  92.  * Get a number from a window.  We limit the length and return a -1
  93.  * on <ESC> key.
  94.  */
  95.  
  96. int
  97. get_num(win, num)
  98. WINDOW *win;
  99. int num;
  100. {
  101.     int count, x, y, number;
  102.     char ans, buf[NUM_WIDTH];
  103.  
  104.     count = 0;
  105.     while ((ans = wgetch(win)) != '\r') {
  106.                     /* do our own backspace */
  107.         if (ans == BS || ans == DEL) {
  108.             if (!count) {
  109.                 beep();
  110.                 continue;
  111.             }
  112.             count--;
  113.             buf[count] = '\0';
  114.             getyx(win, y, x);
  115.             x--;
  116.             wmove(win, y, x);
  117.             waddch(win, (chtype) ' ');
  118.             wmove(win, y, x);
  119.             wrefresh(win);
  120.             continue;
  121.         }
  122.                     /* an <ESC> anywhere in the string */
  123.         if (ans == ESC)
  124.             return(-1);
  125.                     /* only digits are allowed */
  126.         if (ans < '0' || ans > '9') {
  127.             beep();
  128.             continue;
  129.         }
  130.                     /* exceeded the max? */
  131.         if (count >= num || count >= NUM_WIDTH) {
  132.             beep();
  133.             continue;
  134.         }
  135.  
  136.         buf[count] = ans;
  137.         waddch(win, (chtype) ans);
  138.         wrefresh(win);
  139.         count++;
  140.     }
  141.     buf[count] = '\0';
  142.     number = atoi(buf);
  143.     return(number);
  144. }
  145.  
  146. /*
  147.  * Change video attributes while printing a string.  The use of the
  148.  * pre-processor definition NOPROMOTE (located in config.h) means that
  149.  * strings will be printed without any special video attribute if the
  150.  * requested capability doesn't exist.
  151.  */
  152.  
  153. wattrstr(win, attr, str)
  154. WINDOW *win;
  155. chtype attr;
  156. char *str;
  157. {
  158.     int do_it;
  159.                     /* if nothing, do nothing */
  160.     if (str == NULL || *str == '\0')
  161.         return(0);
  162.  
  163. #ifdef OLDCURSES
  164.     if (attr)
  165.         wstandout(win);
  166.     waddstr(win, str);
  167.     if (attr)
  168.         wstandend(win);
  169. #else /* OLDCURSES */
  170.  
  171. #ifdef NOPROMOTE
  172.                     /* does the capability exist? */
  173.     do_it = 0;
  174.     if ((attr & A_STANDOUT) && enter_standout_mode)
  175.         do_it++;
  176.     if ((attr & A_UNDERLINE) && enter_underline_mode)
  177.         do_it++;
  178.     if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode))
  179.         do_it++;
  180.     if ((attr & A_BLINK) && enter_blink_mode)
  181.         do_it++;
  182.     if ((attr & A_BOLD) && enter_bold_mode)
  183.         do_it++;
  184.     if ((attr & A_DIM) && enter_dim_mode)
  185.         do_it++;
  186. #else /* NOPROMOTE */
  187.     do_it = 1;
  188. #endif /* NOPROMOTE */
  189.  
  190.     if (do_it)
  191.         wattron(win, attr);
  192.                     /* print the string */
  193.     waddstr(win, str);
  194.     if (do_it)
  195.         wattroff(win, attr);
  196. #endif /* OLDCURSES */
  197.     return(0);
  198. }
  199.  
  200. /*
  201.  * Change video attributes while printing a character.
  202.  */
  203.  
  204. wattrch(win, attr, c)
  205. WINDOW *win;
  206. chtype attr;
  207. char c;
  208. {
  209.     int do_it;
  210.  
  211.     if (c == '\0')
  212.         return(0);
  213. #ifdef OLDCURSES
  214.     if (attr)
  215.         wstandout(win);
  216.     waddch(win, (chtype) c);
  217.     if (attr)
  218.         wstandend(win);
  219. #else /* OLDCURSES */
  220.  
  221. #ifdef NOPROMOTE
  222.                     /* does the capability exist? */
  223.     do_it = 0;
  224.     if ((attr & A_STANDOUT) && enter_standout_mode)
  225.         do_it++;
  226.     if ((attr & A_UNDERLINE) && enter_underline_mode)
  227.         do_it++;
  228.     if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode))
  229.         do_it++;
  230.     if ((attr & A_BLINK) && enter_blink_mode)
  231.         do_it++;
  232.     if ((attr & A_BOLD) && enter_bold_mode)
  233.         do_it++;
  234.     if ((attr & A_DIM) && enter_dim_mode)
  235.         do_it++;
  236. #else /* NOPROMOTE */
  237.     do_it = 1;
  238. #endif /* NOPROMOTE */
  239.  
  240.     if (do_it)
  241.         wattron(win, attr);
  242.                     /* print the character */
  243.     waddch(win, (chtype) c);
  244.     if (do_it)
  245.         wattroff(win, attr);
  246. #endif /* OLDCURSES */
  247.     return(0);
  248. }
  249.  
  250.  
  251. /*
  252.  * Change video attributes while printing a number.
  253.  */
  254.  
  255. wattrnum(win, attr, num)
  256. WINDOW *win;
  257. chtype attr;
  258. int num;
  259. {
  260.     int do_it;
  261.     char buf[40];
  262.  
  263.     sprintf(buf, "%d", num);
  264.  
  265. #ifdef OLDCURSES
  266.     if (attr)
  267.         wstandout(win);
  268.     waddstr(win, buf);
  269.     if (attr)
  270.         wstandend(win);
  271. #else /* OLDCURSES */
  272.  
  273. #ifdef NOPROMOTE
  274.                     /* does the capability exist? */
  275.     do_it = 0;
  276.     if ((attr & A_STANDOUT) && enter_standout_mode)
  277.         do_it++;
  278.     if ((attr & A_UNDERLINE) && enter_underline_mode)
  279.         do_it++;
  280.     if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode))
  281.         do_it++;
  282.     if ((attr & A_BLINK) && enter_blink_mode)
  283.         do_it++;
  284.     if ((attr & A_BOLD) && enter_bold_mode)
  285.         do_it++;
  286.     if ((attr & A_DIM) && enter_dim_mode)
  287.         do_it++;
  288. #else /* NOPROMOTE */
  289.     do_it = 1;
  290. #endif /* NOPROMOTE */
  291.  
  292.     if (do_it)
  293.         wattron(win, attr);
  294.                     /* print the character */
  295.     waddstr(win, buf);
  296.     if (do_it)
  297.         wattroff(win, attr);
  298. #endif /* OLDCURSES */
  299.     return(0);
  300. }
  301.  
  302. /*
  303.  * Prompt for a Yes or No answer.  Echo the single key input as words.
  304.  * Handle the funny cursor movement problems with magic cookie terminals.
  305.  * Returns a 1 on yes.
  306.  */
  307.  
  308. int
  309. yes_prompt(win, y, x, attr, str)
  310. WINDOW *win;
  311. int y, x;
  312. chtype attr;
  313. char *str;
  314. {
  315.     int ret_code;
  316.     char new_str[80], *strcpy(), *strcat();
  317.                     /* sanity checking */
  318.     if (strlen(str) > 71)
  319.         *(str+71) = '\0';
  320.                     /* build and display the prompt */
  321.     strcpy(new_str, str);
  322.     strcat(new_str, "? (y/n):");
  323.     mvwattrstr(win, y, x, attr, new_str);
  324.     wmove(win, y, strlen(new_str)+x+2);
  325.     wrefresh(win);
  326.  
  327.     ret_code = -1;
  328.     while (ret_code == -1) {
  329.         switch (wgetch(win)) {
  330.             case 'y':
  331.             case 'Y':
  332.                 waddstr(win, "Yes");
  333.                 ret_code = 1;
  334.                 break;
  335.             case 'n':
  336.             case 'N':
  337.             case ESC:
  338.                 waddstr(win, "No");
  339.                 ret_code = 0;
  340.                 break;
  341.             default:
  342.                 beep();
  343.  
  344.         }
  345.     }
  346.     wrefresh(win);
  347.     return(ret_code);
  348. }
  349.  
  350. /*
  351.  * Handy routine for clear-to-end-of-line.  Fixes up the box if requested.
  352.  */
  353.  
  354. int
  355. clear_line(win, y, x, re_box)
  356. WINDOW *win;
  357. int y, x, re_box;
  358. {
  359.     if (wmove(win, y, x) == ERR)
  360.         return(ERR);
  361.  
  362.     wclrtoeol(win);
  363.  
  364.     if (re_box) {
  365.         mvwaddch(win, y, win->_maxx-1, (chtype) ACS_VLINE);
  366.         wmove(win, y, x);
  367.     }
  368.     return(0);
  369. }
  370.  
  371. /*
  372.  * Routine to make a horizontal line.  Does NOT do a wrefresh().
  373.  */
  374.  
  375. int
  376. horizontal(win, x, y, len)
  377. WINDOW *win;
  378. int x, y, len;
  379. {
  380.     wmove(win, x, y);
  381.  
  382.     while (len--)
  383.         waddch(win, ACS_HLINE);
  384.  
  385.     return(0);
  386. }
  387.  
  388. /*
  389.  * Wait for a key or time out.  Returns a -1 on timeout.  This is similar
  390.  * to the half-delay mode in the newer versions of curses(3).
  391.  */
  392.  
  393. static int wk_flag;
  394.  
  395. /* ARGSUSED */
  396. int
  397. wait_key(win, sec)
  398. WINDOW *win;
  399. unsigned int sec;
  400. {
  401.     int key;
  402.     static int wk_force();
  403.     unsigned int alarm();
  404.     char c;
  405.  
  406.     signal(SIGALRM, (SIG_TYPE(*) ()) wk_force);
  407.     wk_flag = 0;
  408.  
  409.     alarm(sec);
  410.  
  411. #ifdef BSD
  412.     if (setjmp(wk_buf))
  413.         return(-1);
  414. #endif /* BSD */
  415.  
  416. #ifdef WGETCH_BROKE
  417.     read(0, &c, 1);
  418.     key = c & 0x7f;
  419. #else /* WGETCH_BROKE */
  420.     key = wgetch(win);
  421. #endif /* WGETCH_BROKE */
  422.  
  423.     if (wk_flag)
  424.         return(-1);
  425.     alarm(0);
  426.     return(key);
  427. }
  428.  
  429. /* ARGSUSED */
  430. static int
  431. wk_force(dummy)
  432. int dummy;
  433. {
  434. #ifdef BSD
  435.     longjmp(wk_buf, 1);
  436. #else /* BSD */
  437.     signal(SIGALRM, (SIG_TYPE(*) ()) wk_force);
  438.     wk_flag = 1;
  439. #endif /* BSD */
  440. }
  441.  
  442. /*
  443.  * Here are some routines that are probably missing from the older
  444.  * flavors of curses(3).
  445.  */
  446.  
  447. #ifdef OLDCURSES
  448. /*
  449.  * Make the terminal bell go off
  450.  */
  451.  
  452. int
  453. beep()
  454. {
  455.     fputc(BEL, stderr);
  456.     return(0);
  457. }
  458.  
  459. /*
  460.  * Take the terminal out of the "curses mode".  The t_mode structure was 
  461.  * captured before we initialized the curses mode.
  462.  */
  463.  
  464. int
  465. resetterm()
  466. {
  467.     extern char _putchar();
  468.     extern struct sgttyb t_mode;
  469.  
  470.     ioctl(0, TIOCSETP, &t_mode);
  471.     tputs(TE, 1, _putchar);
  472.     tputs(VE, 1, _putchar);
  473.     return(0);
  474. }
  475.  
  476. /*
  477.  * Put the terminal back into the "curses mode".  The c_mode structure was
  478.  * captured after we initialized the curses mode.
  479.  */
  480.  
  481. int
  482. fixterm()
  483. {
  484.     extern char _putchar();
  485.     extern struct sgttyb c_mode;
  486.  
  487.     ioctl(0, TIOCSETP, &c_mode);
  488.     tputs(TI, 1, _putchar);
  489.     tputs(VS, 1, _putchar);
  490.     return(0);
  491. }
  492. #endif /* OLDCURSES */
  493.